/**
 * \file Datatype.h
 *
 * ICC General Code Base
 * Written 2010-2011, by Anthony Berlin and Alexander Carlqvist
 *
 * This file is part of ICC.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef DATATYPE_H
#define DATATYPE_H

#include <list>
#include <string>

#include "Object.h"
#include "DatatypeIds.h"

#define UNKNOWN_TYPE "(unknown-type)"

using std::list;
using std::string;

class Datatype : public gc
{
public:
    /// Constructors for 'Datatype'.
    Datatype();
    Datatype(unsigned long int flags,bool isFunc, list<Datatype*>* funcParamDatatypes,
             bool isPointer, bool isArray, const char* lexeme, bool isRef);
    Datatype(unsigned long int flags, bool isFunc, list<Datatype*>* funcParamDatatypes,
             bool isPointer, bool isArray, string* lexeme, bool isRef);
    Datatype(unsigned long int flags, bool isFunc, list<Datatype*>* funcParamDatatypes,
             bool isPointer, bool isArray, string lexeme, bool isRef);
    Datatype(string* from_string, bool isParameter);

    /// Create a new pointer to a datatype, from a string.
    static Datatype* create_from_string(const char* from_string, bool isParameter = false);
    static Datatype* create_from_string(string from_string, bool isParameter = false);

    /// Clone the datatype, returning the copy.
    Datatype* clone();

    /// Removes the function part of (defunctionalizes) this datatype.
    void defunctionalize();

    /// Returns true if this is a function datatype.
    bool is_function() const;

    /// Returns true if this is a pointer.
    bool is_pointer() const;

    /// Returns true if this is an array datatype.
    bool is_array() const;

    /// Returns true if this is a reference datatype.
    bool is_reference() const;

    /// Returns the flags used to describe the datatype.
    unsigned long int get_flags() const;

    /// Returns the linked list of the function parameters that this datatype is declared with,
    /// if it is indeed a function.
    list<Datatype*>* get_function_param_list() const;

    /// Converts the datatype to a human readable string.
    string to_string(bool defunc = false, bool includeFuncParams = false);
private:

    /// The flags that describe the base of datatype.
    unsigned long int m_flags;

    /// The lexeme representing the datatype, if it is userdefined.
    string m_lexeme;

    /// True if this is a function datatype.
    bool m_isFunction;

    /// Contains the parameter datatypes, in case this is a function datatype.
    list<Datatype*>* m_functionParameters;

    /// True if this is a pointer. This is important to know when accessing this datatype,
    /// as it needs to be casted into a Pointer to be used properly, if this flag is true.
    bool m_isPointer;

    /// True if this is an array datatype. This is not an actual part of the datatype, but
    /// rather a flag used for possible semantical checking.
    bool m_isArray;

    /// A pointer to the datatype object that points to this one. Used to create pointers
    /// to datatypes, or pointers to pointers.
    Datatype* m_pointer;

    /// True if this is a reference datatype.
    bool m_isReference;
};

#endif // DATATYPE_H
